package org.hfy.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.hfy.entity.Contract;
import org.hfy.entity.Quotation;
import org.hfy.entity.QuotationItem;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 合同Excel模板处理工具类
 *
 * @author hfy
 * @version 1.0
 */
@Slf4j
public class ContractExcelTemplateProcessor {

    private static final String TEMPLATE_PATH = "/templates/合同模板.xlsx";

    /**
     * 使用Excel模板生成合同
     *
     * @param contract 合同对象
     * @return Excel文件字节数组
     */
    public static byte[] generateContractFromTemplate(Contract contract) {
        try (InputStream templateStream = ContractExcelTemplateProcessor.class.getResourceAsStream(TEMPLATE_PATH)) {

            if (templateStream == null) {
                log.error("合同模板文件不存在: {}", TEMPLATE_PATH);
                throw new RuntimeException("合同模板文件不存在");
            }

            try (XSSFWorkbook workbook = new XSSFWorkbook(templateStream)) {

                // 构建替换数据
                Map<String, String> replacements = buildReplacementData(contract);

                // 替换占位符
                replaceTemplateVariables(workbook, replacements);

                // 处理物料详情表格
                if (contract.getQuotation() != null && contract.getQuotation().getItems() != null) {
                    processItemsTable(workbook, contract.getQuotation().getItems());
                }

                // 输出为字节数组
                try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
                    workbook.write(outputStream);
                    return outputStream.toByteArray();
                }
            }

        } catch (Exception e) {
            log.error("使用模板生成合同Excel失败: {}", e.getMessage(), e);
            throw new RuntimeException("生成合同Excel失败: " + e.getMessage(), e);
        }
    }

    /**
     * 构建替换数据映射
     *
     * @param contract 合同对象
     * @return 替换数据映射
     */
    private static Map<String, String> buildReplacementData(Contract contract) {
        Map<String, String> replacements = new HashMap<>();

        // 合同基础信息
        replacements.put("${合同编号}", contract.getContractNo() != null ? contract.getContractNo() : "");
        replacements.put("${审核状态}", contract.getStatus() != null ? contract.getStatus() : "");
        replacements.put("${审核人}", contract.getAuditBy() != null ? contract.getAuditBy() : "");
        replacements.put("${创建时间}", contract.getCreatedAt() != null ?
            contract.getCreatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : "");
        replacements.put("${审核时间}", contract.getAuditTime() != null ?
            contract.getAuditTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) : "");
        replacements.put("${审核备注}", contract.getAuditRemark() != null ? contract.getAuditRemark() : "");

        // 报价单相关信息
        if (contract.getQuotation() != null) {
            Quotation quotation = contract.getQuotation();

            replacements.put("${报价单号}", quotation.getQuotationNo() != null ? quotation.getQuotationNo() : "");
            replacements.put("${客户代码}", quotation.getCustomerCode() != null ? quotation.getCustomerCode() : "");
            replacements.put("${客户名称}", quotation.getCustomerName() != null ? quotation.getCustomerName() : "");
            replacements.put("${业务员}", quotation.getSalesperson() != null ? quotation.getSalesperson() : "");
            replacements.put("${合同金额}", quotation.getTotalAmount() != null ?
                formatAmount(quotation.getTotalAmount()) : "0.00");
            replacements.put("${付款方式}", quotation.getPaymentMethod() != null ? quotation.getPaymentMethod() : "");
            replacements.put("${是否含税}", quotation.getIsTaxIncluded() != null && quotation.getIsTaxIncluded() ? "是（13%）" : "否");
            replacements.put("${交期要求}", ""); // 暂时设为空，等待确认Quotation实体字段
            replacements.put("${特殊要求}", ""); // 暂时设为空，等待确认Quotation实体字段
            replacements.put("${备注}", quotation.getRemark() != null ? quotation.getRemark() : "");
        } else {
            // 空值处理
            replacements.put("${报价单号}", "");
            replacements.put("${客户代码}", "");
            replacements.put("${客户名称}", "");
            replacements.put("${业务员}", "");
            replacements.put("${合同金额}", "0.00");
            replacements.put("${付款方式}", "");
            replacements.put("${是否含税}", "否");
            replacements.put("${交期要求}", "");
            replacements.put("${特殊要求}", "");
            replacements.put("${备注}", "");
        }

        // 当前日期
        replacements.put("${当前日期}", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));

        return replacements;
    }

    /**
     * 替换模板中的占位符变量
     *
     * @param workbook Excel工作簿
     * @param replacements 替换数据映射
     */
    private static void replaceTemplateVariables(XSSFWorkbook workbook, Map<String, String> replacements) {
        for (int sheetIndex = 0; sheetIndex < workbook.getNumberOfSheets(); sheetIndex++) {
            Sheet sheet = workbook.getSheetAt(sheetIndex);

            for (Row row : sheet) {
                if (row == null) continue;

                for (Cell cell : row) {
                    if (cell == null || cell.getCellType() != CellType.STRING) continue;

                    String cellValue = cell.getStringCellValue();
                    if (cellValue == null || !cellValue.contains("${")) continue;

                    // 替换所有占位符
                    String newValue = cellValue;
                    for (Map.Entry<String, String> entry : replacements.entrySet()) {
                        newValue = newValue.replace(entry.getKey(), entry.getValue());
                    }

                    if (!newValue.equals(cellValue)) {
                        cell.setCellValue(newValue);
                    }
                }
            }
        }
    }

    /**
     * 处理物料详情表格
     *
     * @param workbook Excel工作簿
     * @param items 物料详情列表
     */
    private static void processItemsTable(XSSFWorkbook workbook, List<QuotationItem> items) {
        Sheet sheet = workbook.getSheetAt(0); // 假设物料详情在第一个工作表

        // 查找物料详情表格的起始位置
        int startRow = findItemsTableStartRow(sheet);
        if (startRow == -1) {
            log.warn("未找到物料详情表格标识，跳过物料详情处理");
            return;
        }

        log.info("找到物料详情表格起始行: {}, 物料数量: {}", startRow, items.size());

        // 获取表头行作为模板
        Row headerRow = sheet.getRow(startRow);
        if (headerRow == null) {
            log.warn("物料详情表头行不存在");
            return;
        }

        // 删除现有的数据行（保留表头）
        clearExistingDataRows(sheet, startRow + 1);

        // 添加物料数据行
        for (int i = 0; i < items.size(); i++) {
            QuotationItem item = items.get(i);
            int dataRowIndex = startRow + 1 + i;

            Row dataRow = sheet.createRow(dataRowIndex);
            fillItemDataRow(dataRow, item, i + 1);
        }
    }

    /**
     * 查找物料详情表格的起始行
     * 通过查找包含"序号"或"物料编码"等关键字的行
     */
    private static int findItemsTableStartRow(Sheet sheet) {
        for (int rowIndex = 0; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
            Row row = sheet.getRow(rowIndex);
            if (row == null) continue;

            for (Cell cell : row) {
                if (cell.getCellType() == CellType.STRING) {
                    String cellValue = cell.getStringCellValue();
                    if (cellValue != null && (cellValue.contains("序号") || cellValue.contains("物料编码") ||
                        cellValue.contains("产品名称") || cellValue.contains("${物料详情}"))) {
                        return rowIndex;
                    }
                }
            }
        }
        return -1;
    }

    /**
     * 清除现有的数据行
     */
    private static void clearExistingDataRows(Sheet sheet, int startRow) {
        int lastRowNum = sheet.getLastRowNum();
        for (int i = lastRowNum; i >= startRow; i--) {
            Row row = sheet.getRow(i);
            if (row != null) {
                sheet.removeRow(row);
            }
        }
    }

    /**
     * 填充物料数据行
     *
     * @param dataRow 数据行
     * @param item 物料详情
     * @param itemNo 序号
     */
    private static void fillItemDataRow(Row dataRow, QuotationItem item, int itemNo) {
        int cellIndex = 0;

        // 序号
        dataRow.createCell(cellIndex++).setCellValue(itemNo);

        // 产品名称
        dataRow.createCell(cellIndex++).setCellValue(item.getProductName() != null ? item.getProductName() : "");

        // 物料编码
        dataRow.createCell(cellIndex++).setCellValue(item.getMaterialCode() != null ? item.getMaterialCode() : "");

        // 板厚
        dataRow.createCell(cellIndex++).setCellValue(item.getThickness() != null ? item.getThickness().toString() : "");

        // 外铜
        dataRow.createCell(cellIndex++).setCellValue(item.getOuterCopper() != null ? item.getOuterCopper() : "");

        // 内铜
        dataRow.createCell(cellIndex++).setCellValue(item.getInnerCopper() != null ? item.getInnerCopper() : "");

        // 交货尺寸
        dataRow.createCell(cellIndex++).setCellValue(item.getDeliverySize() != null ? item.getDeliverySize() : "");

        // 拼板
        dataRow.createCell(cellIndex++).setCellValue(item.getPanelization() != null ? item.getPanelization() : "");

        // 表面处理
        dataRow.createCell(cellIndex++).setCellValue(item.getSurfaceTreatment() != null ? item.getSurfaceTreatment() : "");

        // 阻焊
        dataRow.createCell(cellIndex++).setCellValue(item.getSolderMask() != null ? item.getSolderMask() : "");

        // 字符
        dataRow.createCell(cellIndex++).setCellValue(item.getCharacter() != null ? item.getCharacter() : "");

        // 过孔工艺
        dataRow.createCell(cellIndex++).setCellValue(item.getViaProcess() != null ? item.getViaProcess() : "");

        // 测试
        dataRow.createCell(cellIndex++).setCellValue(item.getTesting() != null ? item.getTesting() : "");

        // 数量
        dataRow.createCell(cellIndex++).setCellValue(item.getQuantity() != null ? item.getQuantity() : 0);

        // 单价
        dataRow.createCell(cellIndex++).setCellValue(item.getUnitPrice() != null ? item.getUnitPrice().doubleValue() : 0.0);

        // 测试架费
        dataRow.createCell(cellIndex++).setCellValue(item.getTestingFee() != null ? item.getTestingFee().doubleValue() : 0.0);

        // 工程费
        dataRow.createCell(cellIndex++).setCellValue(item.getCosts() != null && item.getCosts().getEngineeringFee() != null ?
            item.getCosts().getEngineeringFee().doubleValue() : 0.0);

        // 样板费
        dataRow.createCell(cellIndex++).setCellValue(item.getSampleFee() != null ? item.getSampleFee().doubleValue() : 0.0);

        // 合计金额
        dataRow.createCell(cellIndex++).setCellValue(item.getTotalAmount() != null ? item.getTotalAmount().doubleValue() : 0.0);

        // 交期
        dataRow.createCell(cellIndex++).setCellValue(item.getDeliveryDate() != null ?
            item.getDeliveryDate().toString() : "");

        // 备注
        dataRow.createCell(cellIndex++).setCellValue(item.getItemRemark() != null ? item.getItemRemark() : "");
    }

    /**
     * 格式化金额
     *
     * @param amount 金额
     * @return 格式化后的金额字符串
     */
    private static String formatAmount(BigDecimal amount) {
        if (amount == null) {
            return "0.00";
        }
        return String.format("%.2f", amount.doubleValue());
    }
}
